//
// Created by 29108 on 2025/7/15.
//

#ifndef CIRCUIT_BREAKER_H
#define CIRCUIT_BREAKER_H

#include <atomic>
#include <chrono>
#include <functional>
#include <memory>
#include <shared_mutex>
#include <string>
#include <future>
#include <stdexcept>

#include "common/logger/logger.h"


namespace core_services {
    namespace api_gateway {


        class CircuitBreakerOpenException;

        /**
         * @brief 熔断器类 - 实现服务熔断保护机制
         * @details 基于失败率和响应时间的熔断策略，防止级联故障
         *
         * 核心功能：
         * - 三种状态：关闭、开启、半开启
         * - 自动故障检测和恢复
         * - 可配置的熔断阈值
         * - 实时监控和统计
         * - 支持多种熔断策略
         */
        class CircuitBreaker {
        public:
            /**
             * @brief 熔断器状态枚举
             */
            enum class State {
                CLOSED,     ///< 关闭状态：正常处理请求
                OPEN,       ///< 开启状态：拒绝所有请求
                HALF_OPEN   ///< 半开启状态：允许少量请求测试服务恢复
            };

            /**
             * @brief 熔断器配置结构体
             */
            struct Config {
                int failure_threshold = 5;                        ///< 失败阈值
                std::chrono::seconds timeout{30};                 ///< 熔断超时时间
                int success_threshold = 3;                        ///< 半开启状态下的成功阈值
                double failure_rate_threshold = 0.5;              ///< 失败率阈值
                int min_request_threshold = 10;                   ///< 最小请求数阈值
                std::chrono::milliseconds response_timeout{5000}; ///< 响应超时时间
                bool enable_slow_call_detection = true;           ///< 是否启用慢调用检测
                std::chrono::milliseconds slow_call_threshold{3000}; ///< 慢调用阈值

                /**
                 * @brief 从ConfigManager加载配置
                 */
                static Config fromConfigManager();

                /**
                 * @brief 验证配置有效性
                 */
                bool validate() const;
            };

            /**
             * @brief 构造函数
             * @param config 熔断器配置
             */
            explicit CircuitBreaker(const Config& config);

            /**
             * @brief 析构函数
             */
            ~CircuitBreaker();

            // ==================== 请求执行方法 ====================

            /**
             * @brief 执行请求函数
             * @tparam Func 函数类型
             * @param func 要执行的函数
             * @return 函数执行结果
             * @throws CircuitBreakerOpenException 当熔断器开启时抛出
             */
            template<typename Func>
            auto execute(Func&& func) -> decltype(func());

            /**
             * @brief 异步执行请求函数
             * @tparam Func 函数类型
             * @param func 要执行的函数
             * @return 异步执行结果的future
             * @throws std::system_error 当线程创建失败时抛出
             */
            template<typename Func>
            auto executeAsync(Func&& func) -> std::future<decltype(func())>;

            /**
             * @brief 记录请求成功
             */
            void recordSuccess();

            /**
             * @brief 记录请求失败
             * @param exception 异常信息（可选）
             */
            void recordFailure(const std::exception_ptr& exception = nullptr);

            /**
             * @brief 记录慢调用
             * @param duration 调用耗时
             */
            void recordSlowCall(std::chrono::milliseconds duration);

            // ==================== 状态查询方法 ====================

            /**
             * @brief 获取当前状态
             * @return 熔断器状态
             */
            State getState() const;

            /**
             * @brief 检查熔断器是否开启
             * @return true表示开启，false表示关闭或半开启
             */
            bool isOpen() const { return getState() == State::OPEN; }

            /**
             * @brief 检查熔断器是否关闭
             * @return true表示关闭，false表示开启或半开启
             */
            bool isClosed() const { return getState() == State::CLOSED; }

            /**
             * @brief 检查熔断器是否半开启
             * @return true表示半开启，false表示开启或关闭
             */
            bool isHalfOpen() const { return getState() == State::HALF_OPEN; }

        private:
            Config config_;                                        ///< 熔断器配置
            std::atomic<State> state_{State::CLOSED};             ///< 当前状态

            // 统计信息
            std::atomic<int> total_requests_{0};                  ///< 总请求数
            std::atomic<int> successful_requests_{0};             ///< 成功请求数
            std::atomic<int> failed_requests_{0};                 ///< 失败请求数
            std::atomic<int> slow_requests_{0};                   ///< 慢请求数
            std::chrono::steady_clock::time_point last_failure_time_; ///< 最后失败时间
            std::chrono::steady_clock::time_point state_change_time_; ///< 状态变更时间

            // 半开启状态下的测试请求计数
            std::atomic<int> half_open_success_count_{0};
            std::atomic<int> half_open_request_count_{0};

            // 线程安全保护
            mutable std::shared_mutex state_mutex_;

            /**
             * @brief 检查是否应该从开启状态转换到半开启状态
             * @return true表示应该转换
             */
            bool shouldTransitionToHalfOpen() const;

            /**
             * @brief 检查是否应该从关闭状态转换到开启状态
             * @return true表示应该转换
             */
            bool shouldTransitionToOpen() const;

            /**
             * @brief 检查是否应该从半开启状态转换到关闭状态
             * @return true表示应该转换
             */
            bool shouldTransitionToClosed() const;

            /**
             * @brief 状态转换处理
             * @param new_state 新状态
             */
            void transitionToState(State new_state);

            /**
            * @brief 将状态枚举转换为字符串
            * @param state 熔断器状态
            * @return 状态名称字符串
            */
            std::string stateToString(State state) const;
        };

        template<typename Func>
        auto CircuitBreaker::execute(Func &&func) -> decltype(func()) {
            // 检查熔断器状态
            State current_state = getState();

            // 如果熔断器开启，直接拒绝请求
            if (current_state == State::OPEN) {
                LOG_WARNING("熔断器开启，拒绝请求");
                throw CircuitBreakerOpenException("服务暂时不可用");
            }

            // 记录开始时间
            auto start_time = std::chrono::steady_clock::now();

            try {
                // 执行请求函数
                auto result = func();

                // 计算执行时间
                auto end_time = std::chrono::steady_clock::now();
                auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);

                // 检查是否为慢调用
                if (config_.enable_slow_call_detection && duration >= config_.slow_call_threshold) {
                    LOG_WARNING("检测到慢调用: " + std::to_string(duration.count()) + "ms");
                    recordSlowCall(duration);
                } else {
                    // 记录成功
                    recordSuccess();
                }

                return result;

            } catch (const std::exception& e) {
                // 记录失败
                LOG_ERROR("请求执行失败: " + std::string(e.what()));
                recordFailure(std::current_exception());
                throw; // 重新抛出异常
            } catch (...) {
                // 记录未知异常
                LOG_ERROR("请求执行发生未知异常");
                recordFailure(std::current_exception());
                throw; // 重新抛出异常
            }
        }

        template<typename Func>
        auto CircuitBreaker::executeAsync(Func &&func) -> std::future<decltype(func())> {
            // 使用std::packaged_task包装函数，以便返回future
            using ReturnType = decltype(func());
            std::packaged_task<ReturnType()> task([this, func = std::forward<Func>(func)]() {
                return this->execute(func);
            });

            std::future<ReturnType> future = task.get_future();

            // 在新线程中执行任务
            try {
                std::thread worker([task = std::move(task)]() mutable {
                    task();
                });
                worker.detach();
            } catch (const std::system_error& e) {
                // 线程创建失败时抛出异常
                throw;
            }

            return future;
        }

        // ==================== 异常类 ====================

        /**
         * @brief 熔断器开启异常类
         */
        class CircuitBreakerOpenException : public std::runtime_error {
        public:
            explicit CircuitBreakerOpenException(const std::string& message)
                : std::runtime_error("Circuit breaker is open: " + message) {}
        };

    }
}




#endif //CIRCUIT_BREAKER_H
